package graphics;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;

import javax.swing.JPanel;

import logger.Logger;

public class Canvas3D extends JPanel implements ImageObserver, ComponentListener {

	/**
	 * Canvas 3D
	 */
	private static final long serialVersionUID = 1L;

	public boolean		showAxis;
	public Actor		root;
	
	private Graphics3D	G = null;
	
	public Canvas3D() {
		super();
		//
		// Initialize shapes
		//
		G = createGraphics3D();
		root = initActors();
	}
	
	public Actor initActors() {
		Actor	root = new Actor(null);
		root.children.add(
			Actor.Templates.triangle(
				new Vector(-10f, -10f, 0f),
				new Vector(-10f, 10f, 0f), 
				new Vector(10f, -10f, 0f)
			)
		);
		root.children.add(
			Actor.Templates.axis(20f)
		);
		return root;
	}
	
	@Override
	public final void paint(Graphics g) {
		Graphics3D G3D = createGraphics3D();
		G3D.setGraphics(g);
		paint(G3D);
	}

	
	private	Matrix	projection	= Matrix.perspectiveProjection(1f, 2000f);
	private	Matrix	scaling		= Matrix.scaling(2f, 2f, 2f);
	private	Matrix	translation	= Matrix.translation(getWidth()/2f, getHeight()/2f, 0f);

	public void paint(Graphics3D G) {
		// This method will be called when we want to render to a 3D graphics component
		
		G.push(translation);
		G.push(scaling);
		G.push(projection);
		
		//
		// Draw the box
		//
		if (root!=null) {
			root.draw(G);
		} else {
			Logger.println("root is null!");
		}
		Graphics2D		g = (Graphics2D) G.getGraphics();
		
		Logger.println("Painting the image to the graphics object");
		BufferedImage	img;
		img = G.getZbuffer().getArea(this.getVisibleRect());
		if (img!=null) {
			Logger.println(img.getWidth() + " x " + img.getHeight());
			g.drawImage(img, 0, 0, null);
		} else {
			Logger.println("Null image!");
		}
	}
	
	private Graphics3D createGraphics3D() {
		return new Graphics3D(new Zbuffer());
	}
	
	public Graphics3D getGraphics3D() {
		return G;
	}
	
	public void refresh() {
		this.paintImmediately(0,0,getWidth(),getHeight());
	}

	@Override
	public void componentResized(ComponentEvent e) {
		G = createGraphics3D();
		refresh();
	}

	@Override
	public void componentMoved(ComponentEvent e) {
	}

	@Override
	public void componentShown(ComponentEvent e) {
	}

	@Override
	public void componentHidden(ComponentEvent e) {
	}

}
